package com.zplh.zplh_android_yk;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Environment;
import android.text.TextUtils;

import com.zplh.zplh_android_yk.bean.CheckImeiBean;
import com.zplh.zplh_android_yk.bean.TaskBean;
import com.zplh.zplh_android_yk.dao.DaoUtils;
import com.zplh.zplh_android_yk.intf.SendComplete;
import com.zplh.zplh_android_yk.intf.SendReceive;
import com.zplh.zplh_android_yk.ui.MainActivity;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedTransferQueue;

import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import zplh.com.commonlibrary.module.DownLoadModule;
import zplh.com.commonlibrary.networker.NetCustomSubscriber;
import zplh.com.commonlibrary.networker.NetWorker;
import zplh.com.commonlibrary.utils.CommandResult;
import zplh.com.commonlibrary.utils.FileUtils;
import zplh.com.commonlibrary.utils.LogUtils;
import zplh.com.commonlibrary.utils.ScriptUtils;
import zplh.com.commonlibrary.utils.ShellUtils;
import zplh.com.commonlibrary.utils.SystemUtils;
import zplh.com.commonlibrary.utils.ToastUtils;
import zplh.com.resourcelibrary.constants.NetConstant;

import static zplh.com.resourcelibrary.constants.TaskConstant.TASK_CLEAR;
import static zplh.com.resourcelibrary.constants.TaskConstant.TASK_UPDATA;
import static zplh.com.resourcelibrary.constants.TaskConstant.TASK_WX_FIND_DEV;
import static zplh.com.resourcelibrary.constants.TaskConstant.TASK_WX_PHONE_SET;

/**
 * Created by yong hao zeng on 2018/7/3.
 */
public class TaskManager {
    private static boolean isInit;
    private static Vector<TaskBean> taskArrays = new Vector<>();//所有执行的任务列表 用于展示
    private static LinkedTransferQueue<TaskBean> applyTaskArrays = new LinkedTransferQueue<>();//将要执行的列表
    private static Vector<TaskBean> timeTaskArrays = new Vector<>();//等待执行的列表
    private TaskBean currentTaskBean;//当前执行的任务
    private static TaskManager instance;
    private TaskListener taskListener;
    public static boolean isLoopTask;


    public void setTaskListener(TaskListener taskListener) {
        this.taskListener = taskListener;
    }

    private TaskManager(){}

    public synchronized static TaskManager getInstance(){
        if (instance == null){
            synchronized (TaskManager.class) {
                if (instance == null) {
                    instance = new TaskManager();
                }
            }
        }
        return instance;
    }

    public Vector<TaskBean> getTaskArrays() {
        return taskArrays;
    }

    public static void init(InitListener initlistener){
        if (isInit) return;
        taskArrays = new Vector<>();


        loadTaskByDB(new Observer<List<TaskBean>>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onNext(List<TaskBean> taskBeans) {
                if (taskBeans!=null){
                    if (taskArrays ==null)
                        taskArrays = new Vector<>();
                    taskArrays.addAll(taskBeans);
                    //拆分定时与非定时任务
                    for (TaskBean task : taskArrays) {
                        if (task.getState() != TaskBean.STATE_WAIT)
                                continue;
                        if (task.getIsTimeTask()&&!isApplyTask(task)) {
                            timeTaskArrays.add(task);
                        }else {
                            applyTaskArrays.add(task);
                        }
                    }
                initlistener.initSuccess(getInstance());
                }
            }

            @Override
            public void onError(Throwable e) {
                initlistener.initError(e.getMessage());
            }

            @Override
            public void onComplete() {
            }
        });

        isInit = true;

    }

    //判断定时任务是否可以执行了
    private static boolean isApplyTask(TaskBean task) {
        if (!task.getIsTimeTask())
            return true;
        long delayed_time = task.getDelayed_time();
        return delayed_time <= System.currentTimeMillis();

    }

    public TaskBean getCurrentTaskBean() {
        return currentTaskBean;
    }

    //设置任务为错误 要有错误原因
    public void setError(String log_id, String msg){
        if (currentTaskBean == null) return;
        if (TextUtils.equals(log_id,currentTaskBean.getLogId() )){
            currentTaskBean.setStateMsg(msg);
            currentTaskBean.setState(TaskBean.STATE_ERROR);
            currentTaskBean.setEndTime(System.currentTimeMillis());
            return;
        }


        for (TaskBean taskArray : taskArrays) {
            if (TextUtils.equals(log_id,taskArray.getLogId() ))

            {
                taskArray.setStateMsg(msg);
                taskArray.setState(TaskBean.STATE_ERROR);
                break;
            }
        }
    }


    private static void loadTaskByDB(Observer<List<TaskBean>> subscriber) {
        Observable<List<TaskBean>> vectorObservable = Observable.create(emitter -> {
            emitter.onNext(DaoUtils.load10());


        });
            vectorObservable.observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io()).subscribe(subscriber);

    }



    public void addTask(TaskBean taskBean){
        if (immediatelyTask(taskBean) == 1) {
            return;
        }
        if (!isInit) return;// 未初始化 不接受任务
        DaoUtils.add(taskBean);
        taskArrays.add(taskBean);
        taskListener.onAddTask(taskBean);

        if (taskBean.getIsTimeTask())
            timeTaskArrays.add(taskBean);
        else {
            applyTaskArrays.add(taskBean);
        }
    }

    /**
     * 如果是立即执行的任务 则返回1 否则返回0
     *
     * @param taskBean
     * @return
     */
    private int immediatelyTask(TaskBean taskBean) {
        switch (taskBean.getTaskId()) {
            case TASK_WX_FIND_DEV+"":
//                AssetFileDescriptor fd = null;
//                try {
//                    fd = MyApplication.getCurrentActivity().getAssets().openFd("卡路里.mp3");
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }

                return 1;
            case TASK_CLEAR + "":
                TaskManager.getInstance().cleanTask();
                FileUtils.deleteDir(Environment.getExternalStorageDirectory().getPath()+"/ERROR");
                ToastUtils.showToastSuccess(Objects.requireNonNull(MyApplication.getCurrentActivity()),"清除成功");

                return 1;
            case TASK_WX_PHONE_SET+"":
                String gson = taskBean.getDataGson();
                try {
                    JSONObject jsonObject = new JSONObject(gson);
                    JSONObject phoneRadio = jsonObject.getJSONObject("params");
                    String radio = phoneRadio.getString("phoneRadio");
                    switch (radio){
                        case 1+"":
                            SystemUtils.reboot();
                            break;
                        case 2+"":
                            break;

                    }

                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return 1;
            case TASK_UPDATA + "":
                if (currentTaskBean != null)
                    ScriptUtils.stop(currentTaskBean.getPackageName() + ".test");
                else {
                    CommandResult result = ShellUtils.execCommand("ps |grep '.test'", true);
                    if (!TextUtils.isEmpty(result.successMsg)) {
                        String msg = result.successMsg;
                        int com = msg.indexOf("com");

                        if (com != -1) {
                            String packageName = msg.substring(com, msg.length());

                            ShellUtils.execCommand("am force-stop " + packageName, true);
                        }
                    }
                }
                File file = new File(Environment.getExternalStorageDirectory(), "wxzs.apk");
                try {
                    JSONObject params = new JSONObject(taskBean.getDataGson());
                    JSONObject param = params.getJSONObject("params");
                    String version = param.getString("wxzs_version");
                    new DownLoadModule().downLoadFile(MyApplication.getCurrentActivity(),file,version);

                }catch (Exception e){

                    return -1;
                }
                return 1;
        }
        return 0;
    }

    public void deleteTask(TaskBean taskBean){
        if (!isInit) return;
        DaoUtils.delete(taskBean);
    }


    //清除任务
    public void cleanTask() {
        taskArrays.clear();
        applyTaskArrays.clear();
        timeTaskArrays.clear();
        DaoUtils.clean();
        stopTask();
        taskListener.onTaskRefresh(currentTaskBean);

    }

    public void stopTask() {
        if (currentTaskBean != null)
            ScriptUtils.stop(currentTaskBean.getPackageName() + ".test");
        else {
            CommandResult result = ShellUtils.execCommand("ps |grep '.test'", true);
            if (!TextUtils.isEmpty(result.successMsg)) {
                String msg = result.successMsg;
                int com = msg.indexOf("com");
                if (com == -1) return;
                String packageName = msg.substring(com, msg.length());
                ShellUtils.execCommand("am force-stop " + packageName, true);
            }
        }
    }


    /**
     * 遍历定时集合 添加到可执行列表
     */
    public void findApplyTaskByTime() {
        Iterator<TaskBean> iterator = timeTaskArrays.iterator();
        while (iterator.hasNext()){
            TaskBean next = iterator.next();
            if (isApplyTask(next)){
                applyTaskArrays.add(next);
                iterator.remove();
            }
        }
    }


    /**
     * 执行任务  使用
     * @param taskBean
     */
    private  void applyTask(TaskBean taskBean) throws Exception {
        TaskExecutor.applyTask(taskBean);

    }


    /**
     * 递归执行任务
     */
    @SuppressLint("CheckResult")
    public void loopTask(){
        Observable.create((ObservableOnSubscribe<TaskBean>) emitter -> {


            TaskBean taskBean = applyTaskArrays.take();
            if (!BuildConfig.DEBUG) {
                Random random = new Random();
                int i = random.nextInt(30);
                ToastUtils.showToastSuccess(MyApplication.getCurrentActivity(), i + "秒后开始执行任务");
                Thread.sleep(i * 1000);
            }
            currentTaskBean = taskBean;
            JSONObject object = new JSONObject(taskBean.getDataGson());
            sendReceive2Net(taskBean.getLogId(),taskBean.getAcctype(),object.getString("partition"));
            applyTask(taskBean);
            emitter.onNext(taskBean);
         }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> {
                    markErrorTask(currentTaskBean);
                    return currentTaskBean;
                })
                  .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<TaskBean>() {
                        @Override
                        public void onSubscribe(Disposable d) {
                                            isLoopTask = true;
                        }

                        @Override
                        public void onNext(TaskBean taskBean) {
                            LogUtils.d("任务反馈",taskBean.getTaskName()+" :执行完成" );

                            switch (taskBean.getTaskId()){
                                case "100"://飞行模式任务
                                    break;
                                case "89"://跳转任务
                                    break;
                                    default:
                                        restartActivity();
                            }

                            if (taskBean.getState() != TaskBean.STATE_ERROR ){
                                markSuccessTask(taskBean);
                            }else {
                                markErrorTask(taskBean);
                            }
                            taskListener.onTaskRefresh(currentTaskBean);
                            sendCompleteState(taskBean);
                            loopTask();
                        }

                        @Override
                        public void onError(Throwable e) {
                            LogUtils.d("任务反馈:错误", e.getMessage());
                            loopTask();
                        }

                        @Override
                        public void onComplete() {
                            LogUtils.d("任务反馈","onComplete" );

                        }
                    });
    }

    private void restartActivity() {
        Intent intent2 = new Intent(MyApplication.context, MainActivity.class);
        intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        MyApplication.context.startActivity(intent2);
    }

    /**
     * 处理完成的任务
     * @param taskBean
     */
    public void markSuccessTask(TaskBean taskBean) {
        taskBean.setState(TaskBean.STATE_SUCCESS);
        taskBean.setEndTime(System.currentTimeMillis());
        DaoUtils.updata(taskBean);
    }


    /**
     * 标记任务为完成失败
     * @param currentTaskbean
     */
    public void markErrorTask(TaskBean currentTaskbean) {
            currentTaskbean.setState(TaskBean.STATE_ERROR);
            currentTaskbean.setEndTime(System.currentTimeMillis());
            DaoUtils.updata(currentTaskbean);
    }


    /**
     * 接受任务反馈
     * @param logId
     */
        private void sendReceive2Net(String logId,String location,String type){
        SendReceive receive = NetWorker.getInstance().getRetrofit().create(SendReceive.class);
        HashMap<String, String> map = new HashMap<>();
        map.put("uid",UserManager.getInstance().getMid());
        map.put("log_id",logId);
        map.put("location",location);
        Observable<CheckImeiBean> observable = receive.sendReciver(NetConstant.getUrl(type,NetConstant.SEND_RECEIVE),map);
        NetWorker.getInstance().createNetAsync(observable, new NetCustomSubscriber<CheckImeiBean>() {
            @Override
            public void onNext(CheckImeiBean o) {
                ToastUtils.showToastSuccess(MyApplication.getCurrentActivity(),"任务接受反馈成功");
            }

            @Override
            public void onError(Throwable e) {
                super.onError(e);
            }
        });
    }


    /**
     * 任务失败反馈
     */

    private void sendCompleteState(TaskBean taskBean){
        SendComplete complete = NetWorker.getInstance().getRetrofit().create(SendComplete.class);
        String gson = taskBean.getDataGson();
        try {
            JSONObject object = new JSONObject(gson);
            HashMap<String, String> map = new HashMap<>();
            map.put("log_id",taskBean.getLogId());
            map.put("uid",UserManager.getInstance().getMid());
            map.put("location",taskBean.getAcctype());
            if (taskBean.getState() != TaskBean.STATE_SUCCESS) {
                map.put("state", 1 + "");
            }
            else {
                map.put("state",0+"");
            }
            map.put("message",taskBean.getStateMsg());
            Observable observable = complete.sendComplete(NetConstant.getUrl(object.getString("partition"),NetConstant.SEND_COMPLETE),map);
            NetWorker.getInstance().createNetAsync(observable, new NetCustomSubscriber<CheckImeiBean>() {
                @Override
                public void onNext(CheckImeiBean o) {
                    ToastUtils.showToastSuccess(MyApplication.getCurrentActivity(),"任务执行完毕反馈成功");
                }

                @Override
                public void onError(Throwable e) {
                    super.onError(e);
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();

        }


    }

    public void setErrorPath(String log_id,String path) {
        if (currentTaskBean == null) return;
        if (TextUtils.equals(log_id,currentTaskBean.getLogId() )){
            currentTaskBean.setError_path(path);
            return;
        }


        for (TaskBean taskArray : taskArrays) {
            if (TextUtils.equals(log_id,taskArray.getLogId() ))

            {
                taskArray.setError_path(path);
                break;
            }
        }
    }

    public interface InitListener {
        void initSuccess(TaskManager taskManager);

        void initError(String error);

    }

    public static void setTaskArrays(Vector<TaskBean> taskArrays) {
        TaskManager.taskArrays = taskArrays;
    }

    public static BlockingQueue<TaskBean> getApplyTaskArrays() {
        return applyTaskArrays;
    }


    public static Vector<TaskBean> getTimeTaskArrays() {
        return timeTaskArrays;
    }

    public static void setTimeTaskArrays(Vector<TaskBean> timeTaskArrays) {
        TaskManager.timeTaskArrays = timeTaskArrays;
    }

    public interface TaskListener{
        void onAddTask(TaskBean taskBean);
        void onDeleteTask(TaskBean taskBean);
        void onTaskRefresh(TaskBean taskBean);
    }
}
